/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package domain;

import java.io.File;
import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;

/**
 *
 * @author ParaSait
 */
public class DirectoryListener extends Thread {

    private Client client;
    private boolean run;
    private boolean activated;
    private WatchService watcher;
    private Map<WatchKey, Path> keys = new ConcurrentHashMap<WatchKey, Path>();

    public DirectoryListener(Client client) {
        this.client = client;
    }

    public void setRunning(boolean run) {
        this.run = run;
    }

    public void setActivated(boolean activated) {
        this.activated = activated;
    }

    private void registerDirectory(String dir) throws IOException {
        System.out.println(dir);
        Path path = Paths.get(dir);
        if(path != null)
            System.out.println("its not null: " + path);
        
        watcher = FileSystems.getDefault().newWatchService();
        WatchKey key = path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
        keys.put(key, path);
    }

    public void setDirectory(String dir) throws IOException {
        registerDirectory(dir);
    }

    @Override
    public void run() {
        WatchKey key;

        setRunning(true);
        while (run) {
            if (activated) {
                key = null;

                try {
                    key = watcher.poll(10, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    setRunning(false);
                    break;
                } catch (ClosedWatchServiceException e) {
                    e.printStackTrace();
                    setRunning(false);
                    break;
                }

                if (key != null) {
                    Path path = keys.get(key);
                    for (WatchEvent<?> i : key.pollEvents()) {
                        WatchEvent<Path> event = (WatchEvent<Path>) i;
                        WatchEvent.Kind<Path> kind = event.kind();
                        Path name = event.context();
                        File file = new File(name.toUri());

                        System.out.println(kind.toString() + ": " + name.toString());
                        
                        if(file.exists() && !file.isDirectory())
                        {
                            if(kind == ENTRY_MODIFY)
                            {
                                client.deleteServerFile(name.toString());
                                client.sendFile(name.toString());
                            }
                            else if(kind == ENTRY_DELETE)
                            {
                                client.deleteServerFile(name.toString());
                            }
                        }
                    }
                    if (key.reset() == false) {
                        System.out.printf("%s is invalid %n", key);
                        keys.remove(key);
                        if (keys.isEmpty()) {
                            break;
                        }
                    }
                }
            }

            try {
                System.out.println("hush hush... now you sleep");
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(ServerListener.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        try {
            watcher.close();
        } catch (IOException ex) {
            Logger.getLogger(DirectoryListener.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
